package com.lln.cjcx.style;

import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author LiLinnan
 * @version 1.0
 * @date 2020/1/30 17:23
 */

public final class WidthStrategy extends AbstractColumnWidthStyleStrategy {

	private static final int MAX_COLUMN_WIDTH = 255;

	private final Map<Integer, Map<Integer, Integer>> CACHE = new HashMap<>(8);

	@Override
	protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head,
								  Integer relativeRowIndex, Boolean isHead) {
		boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
		if (!needSetWidth) {
			return;
		}
		Map<Integer, Integer> maxColumnWidthMap = CACHE.computeIfAbsent(writeSheetHolder.getSheetNo(), k -> new HashMap<>(16));
		Integer columnWidth = dataLength(cellDataList, cell, isHead);
		if (columnWidth < 0) {
			return;
		}
		if (columnWidth > MAX_COLUMN_WIDTH) {
			columnWidth = MAX_COLUMN_WIDTH;
		}
		Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
		if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
			maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
			writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 300);
		}
	}

	private Integer dataLength(@SuppressWarnings("rawtypes") List<CellData> cellDataList, Cell cell, Boolean isHead) {
		if (isHead) {
			return cell.getStringCellValue().getBytes().length;
		}
		//noinspection rawtypes
		CellData cellData = cellDataList.get(0);
		CellDataTypeEnum type = cellData.getType();
		if (type == null) {
			return -1;
		}
		switch (type) {
			case STRING:
				return cellData.getStringValue().getBytes().length;
			case BOOLEAN:
				return cellData.getBooleanValue().toString().getBytes().length;
			case NUMBER:
				return cellData.getNumberValue().toString().getBytes().length;
			default:
				return -1;
		}
	}
}
